/*
 * Copyright 2007 National Bioinformatics Network
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package dgbgui.gui.widgets;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import dgbgui.gui.widgets.visual.QueryWidget;
import dgbgui.gui.widgets.visual.modeldriven.ModelDrivenConceptWidget;
import dgbgui.gui.widgets.visual.results.ResultWidget;
import dgbgui.modeldocument.Query;
import dgbgui.modeldocument.primitives.Concept;
import dgbgui.modeldocument.primitives.Primitive;

/**
 * @author bjnortier
 * The widget store contains all the currenlt widgets, with methods
 * for adding, removing and lookups
 */
/**
 * @author bjnortier
 *
 */
/**
 * @author bjnortier
 *
 */
public class WidgetStore {
    
    /**
     * Add a query widget to the store
     * @param query
     * @param widget
     */
    public void addWidget(Query query, QueryWidget widget) {
        // Add to the lookup 
        if ( m_queryWidgetMap.get(query) == null ) {
            m_queryWidgetMap.put(query, new HashSet<QueryWidget>());
        }
        m_queryWidgetMap.get(query).add(widget);
        // Also add to the reverse lookup
        m_queryLookupMap.put(widget, query);
    }
    
    /**
     * Add a result widget to the store
     * @param primitive
     * @param widget
     */
    public void addWidget(Primitive primitive, ResultWidget widget) {
        // Add to the lookup 
        if ( m_primitiveResultMap.get(primitive) == null ) {
            m_primitiveResultMap.put(primitive, new HashSet<ResultWidget>());
        }
        m_primitiveResultMap.get(primitive).add(widget);
        // Also add to the reverse lookup
        m_primitiveLookupMap.put(widget, primitive);
    }
    
    
    public Set<QueryWidget> getWidgets(Query query) {
        if ( m_queryWidgetMap.get(query) == null ) {
            m_queryWidgetMap.put(query,new HashSet<QueryWidget>());
        }
        return m_queryWidgetMap.get(query);
    }
    
    public Set<ResultWidget> getWidgets(Primitive primitive) {
        if ( m_primitiveResultMap.get(primitive) == null ) {
            m_primitiveResultMap.put(primitive,new HashSet<ResultWidget>());
        }
        return m_primitiveResultMap.get(primitive);
    }
    

    public Query getQuery(QueryWidget widget) {
        return m_queryLookupMap.get(widget);
    }
    

    public Primitive getPrimitive(ResultWidget widget) {
        return m_primitiveLookupMap.get(widget);
    }
    

    public void remove(Query query) {
        // Only root queries are in the store, so no need to worry
        // about nested queries
        Set<QueryWidget> queryWidgets = m_queryWidgetMap.get(query); 
        for ( QueryWidget widget : queryWidgets ) {
            widget.removeFromParent();
            m_queryLookupMap.remove(widget);
        }
        m_queryWidgetMap.remove(query);
    }
    
    public void remove(Primitive primitive) {
        // Remove from both maps
        Set<ResultWidget> resultWidgets = m_primitiveResultMap.get(primitive); 
        if ( resultWidgets != null ) {
            for ( ResultWidget widget : resultWidgets ) {
                widget.removeFromParent();
                m_queryLookupMap.remove(widget);
            }
            m_primitiveResultMap.remove(primitive);
        }
    }
    
    
    public void addWidget(Concept concept, ModelDrivenConceptWidget widget) {
        // Add to the lookup and reverse lookup 
        m_modelDrivenWidgetmap.put(concept,widget);
        // Also add to the reverse lookup
        m_modelLookupMap.put(widget, concept);
    }
    
    public ModelDrivenConceptWidget getModelDrivenWidget(Concept concept) {
        return m_modelDrivenWidgetmap.get(concept);
    }
    
    
    
    // ---------- Singleton ----------
    
    public static WidgetStore getInstance() {
        if ( m_instance == null ) {
            m_instance = new WidgetStore();
        }
        return m_instance;
    }
    
    private WidgetStore() {
        // Do nothing. Private ctor for singleton
    }
    
    static WidgetStore m_instance;
    
    // ---------- Fields ----------
    
    // Map of query to widgets
    Map<Query,Set<QueryWidget>> m_queryWidgetMap = new HashMap<Query,Set<QueryWidget>>();
    // Map of primitives to result widgets
    Map<Primitive,Set<ResultWidget>> m_primitiveResultMap = new HashMap<Primitive,Set<ResultWidget>>();
    
    // Reverse lookup for query widgets
    Map<QueryWidget, Query> m_queryLookupMap = new HashMap<QueryWidget,Query>();
    // Reverse lookup for result widgets
    Map<ResultWidget, Primitive> m_primitiveLookupMap = new HashMap<ResultWidget,Primitive>();
    
    // Map of model to widgets
    Map<Concept,ModelDrivenConceptWidget> m_modelDrivenWidgetmap = new HashMap<Concept,ModelDrivenConceptWidget>();
    // Reverse lookup
    Map<ModelDrivenConceptWidget, Concept> m_modelLookupMap = new HashMap<ModelDrivenConceptWidget,Concept>();
    
    

}
